#include "database.h"
#include "protocol.h"
#include "article.h"


using namespace std;
namespace client_server {

	/* Create/setups the database */
	Database::Database(){
		maxIndex = 0;
	}
		
	/* Kills the database */
	Database::~Database(){
		
	}
		
	/* Creates a new newsgroup. Throws exception if newsgroup already exists */
	void Database::create_newsgroup(std::string name) throw(DatabaseException){
		vector<pair<int, string> >::const_iterator itr = newsgroups.begin();
		
		while(itr != newsgroups.end()) {
			if(itr->second.compare(name) == 0) {
				DatabaseException dbe;
				dbe.id = protocol::Protocol::ERR_NG_ALREADY_EXISTS;
				throw dbe;
			}
			++itr;
		}
		newsgroups.push_back(make_pair(++maxIndex, name));
		articles.insert(make_pair(maxIndex, vector<Article>()));
	}
		
	/* Deletes a newsgroup. Throws exception if newsgroup does not exist */
	void Database::delete_newsgroup(int group_id) throw(DatabaseException){
		map<int, vector<Article> >::const_iterator itr = articles.find(group_id);
		if(itr == articles.end()){
			DatabaseException dbe;
			dbe.id = protocol::Protocol::ERR_NG_DOES_NOT_EXIST;
			throw dbe;
		}
		vector<pair<int, string> >::iterator itr2 = newsgroups.begin();
		while(itr2 != newsgroups.end()) {
			if(itr2->first == group_id) {
				newsgroups.erase(itr2);
				break;
			}
			itr2++;
		}
		articles.erase(group_id);
	}
		
	/* Returns a vector with pairs of all newsgroupId + newsgroup name. */
	std::vector<std::pair<int, string> > Database::list_newsgroups(){
		return newsgroups;
	}		
		
	/* Creates a new article. Throws exception if newsgroup does not exist. */
	void Database::create_article(int group_id, std::string name, std::string author, std::string content) throw(DatabaseException){
		map<int, vector<Article> >::const_iterator itr = articles.find(group_id);
		if(itr == articles.end()){
			DatabaseException dbe;
			dbe.id = protocol::Protocol::ERR_NG_DOES_NOT_EXIST;
			throw dbe;
		}
		articles[group_id].push_back(Article(name, author, content));
	}
    		
    	/* Deletes an article. Throws exception if newsgroup or article does not exist. */
	void Database::delete_article(int group_id, int art_id) throw(DatabaseException){
		map<int, vector<Article> >::const_iterator itr = articles.find(group_id);
		if(itr == articles.end()){
			DatabaseException dbe;
			dbe.id = protocol::Protocol::ERR_NG_DOES_NOT_EXIST;
			throw dbe;
		}
		if(itr->second.size() < static_cast<unsigned int>(art_id)){
			DatabaseException dbe;
			dbe.id = protocol::Protocol::ERR_ART_DOES_NOT_EXIST;
			throw dbe;
		}
		articles[group_id].erase(articles[group_id].begin() + art_id);
	}
		
	/* Returns a vector with pairs of all articleId + article name or empty vector if no articles exists in the newsgroup. */
	vector<pair<int, string> > Database::list_articles(int group_id) throw(DatabaseException){
		map<int, vector<Article> >::const_iterator itr = articles.find(group_id);
		if(itr == articles.end()){
			DatabaseException dbe;
			dbe.id = protocol::Protocol::ERR_NG_DOES_NOT_EXIST;
			throw dbe;
		}
		vector<pair<int, string> > names;
		for(size_t i = 0; i < articles[group_id].size(); i++) {
			names.push_back(make_pair(i, articles[group_id][i].get_name()));
		}
		return names;	
	}
		
	/* Returns an article object with the requested article. Throws exception if newsgroup or article does not exist. */
	Article Database::get_article(int group_id, int art_id) throw(DatabaseException){
		map<int, vector<Article> >::const_iterator itr = articles.find(group_id);
		if(itr == articles.end()){
			DatabaseException dbe;
			dbe.id = protocol::Protocol::ERR_NG_DOES_NOT_EXIST;
			throw dbe;
		}
		if(itr->second.size() <= static_cast<unsigned int>(art_id)){
			DatabaseException dbe;
			dbe.id = protocol::Protocol::ERR_ART_DOES_NOT_EXIST;
			throw dbe;
		}
		return (itr->second)[art_id];
	}		

}
